package cc.rengu.oltp.utility.util;

public class PINUtil {
    private static final int ENCRYPT = 1;
    private static final int DECRYPT = 0;

    /**
     * 转pin,从3des转3des加密
     *
     * @param pin    密码
     * @param srcKey 源密钥
     * @param cardNo 卡号
     * @param dstKey 目的密钥
     * @return 转加密后的密码密文
     */
    public static String transPinDes3ToDes3(String pin, String srcKey, String cardNo, String dstKey) {

        /*取主账号的右 12 位（不包括最右边的校验位），主账号不足 12位左补 0*/
        String pan = cardNo.substring(0, cardNo.length() - 1);
        if (pan.length() < 12) {
            pan = String.format("%0" + (12 - pan.length()) + "d", 0) + pan;
        } else {
            pan = pan.substring(pan.length() - 12);
        }
        //先解密3DES加密的PIN
        byte[] srcKeyByte = ByteUtil.hexStringToByte(srcKey);
        byte[] pinByte = ByteUtil.hexStringToByte(pin);
        byte[] pinBlock = DES3Util.decryptMode3DESDouble(srcKeyByte, pinByte);
        if (pinBlock == null) {
            return null;
        }
        //pinBlock ^ PAN
        String pan16 = "0000" + pan;
        byte[] panByte = ByteUtil.hexStringToByte(pan16);

        for (int i = 0; i < 8; i++) {
            pinBlock[i] = (byte) (pinBlock[i] ^ panByte[i]);
        }
        byte[] dstKeyByte = ByteUtil.hexStringToByte(dstKey);
        byte[] dstPinByte = DES3Util.encryptMode3DESDouble(dstKeyByte, pinBlock);
        return ByteUtil.bytesToHexString(dstPinByte);
    }

    /**
     * 转pin,从3des转sm4加密
     *
     * @param pin     密码
     * @param des3Key 源密钥
     * @param cardNo  卡号
     * @param sm4Key  目的密钥
     * @return 转加密后的密码密文
     */
    public static String transPinDes3ToSm4(String pin, String des3Key, String cardNo, String sm4Key) {
        /*取主账号的右 12 位（不包括最右边的校验位），主账号不足 12位左补 0*/
        String pan = cardNo.substring(0, cardNo.length() - 1);
        if (pan.length() < 12) {
            pan = String.format("%0" + (12 - pan.length()) + "d", 0) + pan;
        } else {
            pan = pan.substring(pan.length() - 12);
        }
        System.out.println("12位PAN=[" + pan + "]");
        /*先解密3DES加密的PIN*/
        byte[] key3Des = ByteUtil.hexStringToByte(des3Key);
        byte[] pinByte = ByteUtil.hexStringToByte(pin);
        byte[] pinBlock = DES3Util.decryptMode3DESDouble(key3Des, pinByte);
        if (pinBlock == null) {
            return null;
        }
        //pinBlock ^ PAN
        String pan16 = "0000" + pan;
        byte[] panByte = ByteUtil.hexStringToByte(pan16);

        for (int i = 0; i < 8; i++) {
            pinBlock[i] = (byte) (pinBlock[i] ^ panByte[i]);
        }
        int pinLength = pinBlock[0];
        byte[] pinPlain = new byte[pinLength];
        System.arraycopy(pinBlock, 1, pinPlain, 0, pinLength / 2);

        //PIN按照SM4算法补位,4-12 位数字的 PIN(每个数字占 4 个 BIT) )，不足部分右补F
        String pinSm4 = String.format("%02d", pinLength) + ByteUtil.bytesToHexString(pinPlain);
        byte[] fillByte = new byte[16 - pinSm4.length() / 2];
        java.util.Arrays.fill(fillByte, (byte) 255);
        pinSm4 = pinSm4 + ByteUtil.bytesToHexString(fillByte);
        //PAN按照SM4算法补位,取主账号的右 12 位（不包括最右边的校验位），主账号不足12位左补0
        String panSm4 = String.format("%020d", 0) + pan;

        byte[] pinSm4Byte = ByteUtil.hexStringToByte(pinSm4);
        byte[] panSm4byte = ByteUtil.hexStringToByte(panSm4);
        byte[] keySm4Byte = ByteUtil.hexStringToByte(sm4Key);
        //PINBLOCK 异或 PAN
        for (int i = 0; i < 16; i++) {
            pinSm4Byte[i] = (byte) (pinSm4Byte[i] ^ panSm4byte[i]);
        }
        byte[] destPin = new byte[16];
        //使用SM4密钥加密上一步的PIN明文
        SM4Util.sms4(pinSm4Byte, 16, keySm4Byte, destPin, ENCRYPT);
        return ByteUtil.bytesToHexString(destPin);
    }

    /**
     * 转pin,从sm4转sm4加密
     *
     * @param pin    密码
     * @param srcKey 源密钥
     * @param cardNo 卡号
     * @param desKey 目的密钥
     * @return 转加密后的密码密文
     */
    public static String transPinSm4ToSm4(String pin, String srcKey, String cardNo, String desKey) {
        /*取主账号的右 12 位（不包括最右边的校验位），主账号不足 12位左补 0*/
        String pan = cardNo.substring(0, cardNo.length() - 1);
        if (pan.length() < 12) {
            pan = String.format("%0" + (12 - pan.length()) + "d", 0) + pan;
        } else {
            pan = pan.substring(pan.length() - 12);
        }
        /*先解密sm4加密的PIN*/
        byte[] sm4SrcKey = ByteUtil.hexStringToByte(srcKey);
        byte[] pinByte = ByteUtil.hexStringToByte(pin);
        byte[] pinBlock = new byte[16];
        //使用SM4密钥加密上一步的PIN明文
        SM4Util.sms4(pinByte, 16, sm4SrcKey, pinBlock, DECRYPT);
        byte[] destPin = new byte[16];
        //使用SM4密钥加密上一步的PIN明文
        SM4Util.sms4(pinBlock, 16, ByteUtil.hexStringToByte(desKey), destPin, ENCRYPT);
        return ByteUtil.bytesToHexString(destPin);
    }
}